package cat.joronya.supermanager.service;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Hashtable;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.HTTP;

import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.util.Log;
import cat.joronya.supermanager.Supermanager;
import cat.joronya.supermanager.market.Player;
import cat.joronya.supermanager.team.Team;

/**
 * Recuperem el llistat de teams and it's details.
 * 
 * @author pol
 */
public class MyTeamsSync extends Object
{
	private static final String TAG = "supermanager";
	
	// el service
	private SupermanagerService service;
	
	// el client http on fer les peticions
	private DefaultHttpClient client = null;
	
	// status de retorn
	public int status = -1;
	
	// teams GET
	private static final String TEAMS_LIST_GET = InitSync.BASE_URL+"/verequipos.php";
	// team detail
	private static final String TEAM_DETAIL_GET = InitSync.BASE_URL+"/verequipo.php";
	// day matches GET
	private static final String DAYMATCHES_GET = "http://www.acb.com/resulcla.php?codigo=LACB-58&jornada=1&resultados=";
	
	// dades extretes de les pagines
	public ArrayList<Team> teams;
	public ArrayList<Team> detailTeams;
	
	// hash per guardar team vs team
	protected Hashtable<String, String> dayMatches = null;

	// jornada passada de loginSyn pq no es a les pagines de market
	private Integer jornada = null;
	
	/**
	 * Constructor amb el intentService que el crida.
	 * @param intentService
	 */
	public MyTeamsSync(SupermanagerService service, DefaultHttpClient client, Integer jornada)
	{
		this.service = service;
		this.client = client;
		this.jornada = jornada;
		
		this.dayMatches = new Hashtable<String, String>();
	}
	
	protected void execute()
	{
		try
		{
			// checkejem per connectivitat
			ConnectivityManager cm = (ConnectivityManager) service.getSystemService(Context.CONNECTIVITY_SERVICE);
			boolean online = cm.getActiveNetworkInfo().isConnectedOrConnecting();
			
			if( !online )
				throw new ConnectivityException();
			
			// cridem per parsejar partits de la jornada
			executeDayMatches();
			
			// parsejem my teams
			executeMyTeams();
		}
		catch(ConnectivityException ce){
			// error de connectivitat
			status = Supermanager.CONNECTIVITY_ERROR_STATUS;
	        Log.d(TAG, "MyTeamsSync status: CONNECTIVITY_ERROR_STATUS - "+status);
			return;
		}
		catch(Exception e){
			// altre error, notifiquem i anem offline
			status = Supermanager.OTHER_ERROR_STATUS;
	        Log.d(TAG, "MyTeamsSync status: OTHER_ERROR_STATUS - "+status);
			return;
		}
    }
	
	protected void executeMyTeams() throws Exception
	{
		HttpGet plHttpGet = new HttpGet(TEAMS_LIST_GET);
		HttpResponse response = client.execute(plHttpGet);
		ByteArrayOutputStream os = new ByteArrayOutputStream();
        response.getEntity().writeTo(os);
        String teamsPage = os.toString(HTTP.ISO_8859_1);
        
        MyTeamParser myTeamParser = new MyTeamParser();
        teams = myTeamParser.parse(teamsPage);
        
		// de cada team updatem valors i parsejem el detall
        detailTeams = new ArrayList<Team>();
        for(Team team: teams)
        {
        	Team parsedTeamDetail = getTeamDetail(team);
        	detailTeams.add(parsedTeamDetail);
        }
        
        // parsejat ok
        status = Supermanager.MY_TEAMS_PARSED_OK;
        Log.d(TAG, "MyTeamsSync status: MY_TEAMS_PARSED_OK - "+status);
        return;
	}
	
	protected Team getTeamDetail(Team team) 
		throws Exception
	{
		HttpGet plHttpGet = new HttpGet(TEAM_DETAIL_GET+"?id_equ="+team.getIdEqu());
		HttpResponse response = client.execute(plHttpGet);
		ByteArrayOutputStream os = new ByteArrayOutputStream();
        response.getEntity().writeTo(os);
        String teamPage = os.toString(HTTP.ISO_8859_1);
        
        MyTeamDetailParser myTeamDetailParser = new MyTeamDetailParser();
        Team parsedTeamDetail = myTeamDetailParser.parse(team.getIdEqu(), teamPage);

        return parsedTeamDetail;
	}
	
	private void executeDayMatches() throws Exception 
	{
		HttpGet plHttpGet = new HttpGet(DAYMATCHES_GET + jornada);
		HttpResponse response = client.execute(plHttpGet);

		ByteArrayOutputStream os = new ByteArrayOutputStream();
		response.getEntity().writeTo(os);
		String dayMatchesPage = os.toString(HTTP.ISO_8859_1);

		DayMatchesParser dayMatchesParser = new DayMatchesParser();
		this.dayMatches = dayMatchesParser.parse(dayMatchesPage);
	}

	/**
	 * Guardar les dades trobades a DB.
	 */
    protected void onPostExecute(Uri uri) 
    {
    	// tractem cada team del llistat
    	Log.d(TAG,"Parsed "+teams.size()+" teams, going to insert/update");
    	for(Team team: teams)
    	{
    		// nomes guardem dades del llistat al insert/update
			insertOrUpdateTeam(uri, team);
			
			// guardem dades de jornada actual: status, team_players...
			insertOrUpdateTeamNextDay(uri, team);
    	}
    	
    	// tractem cada detailTeam, guardem dades de pagina interior
    	// hi ha dades del MyTeam i dades del MyTeamDetail (players)
    	for(Team team: detailTeams)
    	{
    		// guardar dades de header equip, tant de day com del yourWeekDay
    		insertOrUpdateTeamDetailDay(uri, team);
    		// when the team is new, no dayWeek data present, so nothing to save
    		if( team.getYourWeekDay() != null )
    			insertOrUpdateTeamDetailYourWeekDay(uri, team);
    		else
    			Log.d(TAG, "MyTeamsSyng myTeam just newly created, no last day statistics present on team");
    		
    		// equip sense jugadors
    		if( team.getPlayers() == null )
    		{
    			Log.d(TAG,"Team ["+team.getName()+"] has no players");
    			continue;
    		}
    		
    		// guardem els jugadors
    		for(Player player: team.getPlayers().values())
    		{
    			// insert or update team player
    			insertOrUpdateMyTeamPlayer(team.getIdEqu(), team.getDay().toString(), player);
    		}
    	}
    }
    
    /**
	 * Insert or Update Team as needed, but just information from initial list page.
	 * @param uri
	 * @param pl
	 * @return
	 */
	private String insertOrUpdateTeam(Uri uri, Team team)
	{
		// insertem al team les dades de day == yourWeekDay
		ContentValues values = new ContentValues();
		values.put(Supermanager.MyTeam.ID_EQU, team.getIdEqu());
		values.put(Supermanager.MyTeam.DAY, team.getDay());
		values.put(Supermanager.MyTeam.NAME, team.getName());
		//values.put(Supermanager.MyTeam.STATUS, team.getStatus());
		//values.put(Supermanager.MyTeam.TEAM_PLAYERS, team.getTeamPlayers().toString());
		values.put(Supermanager.MyTeam.POINTS, team.getPoints());
		values.put(Supermanager.MyTeam.GENERAL, team.getGeneral());
		values.put(Supermanager.MyTeam.BROKER, team.getBroker());
		values.put(Supermanager.MyTeam.POINTS_CLASSIFICATION, team.getPointsClassification());
		values.put(Supermanager.MyTeam.GENERAL_CLASSIFICATION, team.getGeneralClassification());
		values.put(Supermanager.MyTeam.BROKER_CLASSIFICATION, team.getBrokerClassification());
		
		Uri teamUri = Supermanager.MyTeam.CONTENT_URI;
		String lastPathSegment = "0";
		
		// si update no retorna 1 reg, llavors insert
		if( service.getContentResolver().update(uri, 
				values, 
				Supermanager.MyTeam.ID_EQU+" = ? AND "+
				Supermanager.MyTeam.DAY+" = ? ", 
				new String[]{team.getIdEqu(), team.getDay().toString()}) == 0 )
		{
			teamUri = service.getContentResolver().insert(uri, values);
			lastPathSegment = teamUri.getLastPathSegment();
			Log.d(TAG, "Inserting team list data [" + team.getName()
					+ "] with Uri [" + teamUri + "] lastPathSegment ["
					+ lastPathSegment + "] with status: " + team.getStatus()
					+ " and teamPlayers: " + team.getTeamPlayers());
		}
		else
		{
			Cursor cursor = service.getContentResolver().
				query(Supermanager.MyTeam.CONTENT_URI, 
					  Supermanager.MyTeam.PROJECTION, 
					  Supermanager.MyTeam.ID_EQU+" = ? AND "+
					  Supermanager.MyTeam.DAY+" = ? ", 
					  new String[]{team.getIdEqu(), team.getDay().toString()}, 
					  Supermanager.MyTeam.DEFAULT_SORT_ORDER);
			
			if( cursor.moveToFirst() )
			{
				lastPathSegment = ""+cursor.getLong(0);
				teamUri = ContentUris.withAppendedId(Supermanager.MyTeam.CONTENT_URI, cursor.getLong(0));
			}
			Log.d(TAG, "Updating team list data [" + team.getName()
					+ "] with Uri [" + teamUri + "] lastPathSegment ["
					+ lastPathSegment + "] with status: " + team.getStatus()
					+ " and teamPlayers: " + team.getTeamPlayers());
		}
		
		return lastPathSegment;
	}

    /**
	 * Insert or Update Team data for next day as needed, but just information from initial list page.
	 * @param uri
	 * @param pl
	 * @return
	 */
	private String insertOrUpdateTeamNextDay(Uri uri, Team team)
	{
		// insertem al team les dades de day == yourWeekDay
		ContentValues values = new ContentValues();
		values.put(Supermanager.MyTeam.ID_EQU, team.getIdEqu());
		values.put(Supermanager.MyTeam.DAY, jornada+"");
		values.put(Supermanager.MyTeam.NAME, team.getName());
		values.put(Supermanager.MyTeam.STATUS, team.getStatus());
		values.put(Supermanager.MyTeam.TEAM_PLAYERS, team.getTeamPlayers().toString());
		
		Uri teamUri = Supermanager.MyTeam.CONTENT_URI;
		String lastPathSegment = "0";
		
		// si update no retorna 1 reg, llavors insert
		if( service.getContentResolver().update(uri, 
				values, 
				Supermanager.MyTeam.ID_EQU+" = ? AND "+
				Supermanager.MyTeam.DAY+" = ? ", 
				new String[]{team.getIdEqu(), jornada+""}) == 0 )
		{
			teamUri = service.getContentResolver().insert(uri, values);
			lastPathSegment = teamUri.getLastPathSegment();
			Log.d(TAG, "Inserting team list data [" + team.getName()
					+ "] with Uri [" + teamUri + "] lastPathSegment ["
					+ lastPathSegment + "] with status: " + team.getStatus()
					+ " and teamPlayers: " + team.getTeamPlayers());
		}
		else
		{
			Cursor cursor = service.getContentResolver().
				query(Supermanager.MyTeam.CONTENT_URI, 
					  Supermanager.MyTeam.PROJECTION, 
					  Supermanager.MyTeam.ID_EQU+" = ? AND "+
					  Supermanager.MyTeam.DAY+" = ? ", 
					  new String[]{team.getIdEqu(), jornada+""}, 
					  Supermanager.MyTeam.DEFAULT_SORT_ORDER);
			
			if( cursor.moveToFirst() )
			{
				lastPathSegment = ""+cursor.getLong(0);
				teamUri = ContentUris.withAppendedId(Supermanager.MyTeam.CONTENT_URI, cursor.getLong(0));
			}
			Log.d(TAG, "Updating team list data [" + team.getName()
					+ "] with Uri [" + teamUri + "] lastPathSegment ["
					+ lastPathSegment + "] with status: " + team.getStatus()
					+ " and teamPlayers: " + team.getTeamPlayers());
		}
		
		return lastPathSegment;
	}

	/**
	 * Insert or Update Team as needed, but just information from detail page
	 * relative to day.
	 * @param uri
	 * @param pl
	 * @return
	 */
	private String insertOrUpdateTeamDetailDay(Uri uri, Team team)
	{
		// insertem al team les dades amb day = day
		ContentValues values = new ContentValues();
		values.put(Supermanager.MyTeam.ID_EQU, team.getIdEqu());
		values.put(Supermanager.MyTeam.DAY, team.getDay());
		values.put(Supermanager.MyTeam.NAME, team.getName());
		values.put(Supermanager.MyTeam.CASH, team.getCash());
		values.put(Supermanager.MyTeam.CANCEL_CHANGES, team.getCancelChanges());
		
		Uri teamUri = Supermanager.MyTeam.CONTENT_URI;
		String lastPathSegment = "0";
		
		// si update no retorna 1 reg, llavors insert
		if( service.getContentResolver().update(uri, 
				values, 
				Supermanager.MyTeam.ID_EQU+" = ? AND "+
				Supermanager.MyTeam.DAY+" = ? ", 
				new String[]{team.getIdEqu(), team.getDay().toString()}) == 0 )
		{
			teamUri = service.getContentResolver().insert(uri, values);
			lastPathSegment = teamUri.getLastPathSegment();
			Log.d(TAG, "Inserting team detail day data [" + team.getName()
					+ "] with Uri [" + teamUri + "] lastPathSegment ["
					+ lastPathSegment + "] with status: " + team.getStatus()
					+ " and teamPlayers: " + team.getTeamPlayers());
		}
		else
		{
			Cursor cursor = service.getContentResolver().
				query(Supermanager.MyTeam.CONTENT_URI, 
					  Supermanager.MyTeam.PROJECTION, 
					  Supermanager.MyTeam.ID_EQU+" = ? AND "+
					  Supermanager.MyTeam.DAY+" = ? ", 
					  new String[]{team.getIdEqu(), team.getDay().toString()}, 
					  Supermanager.MyTeam.DEFAULT_SORT_ORDER);
			
			if( cursor.moveToFirst() )
			{
				lastPathSegment = ""+cursor.getLong(0);
				teamUri = ContentUris.withAppendedId(Supermanager.MyTeam.CONTENT_URI, cursor.getLong(0));
			}
			Log.d(TAG, "Updating team detail day data [" + team.getName()
					+ "] with Uri [" + teamUri + "] lastPathSegment ["
					+ lastPathSegment + "] with status: " + team.getStatus()
					+ " and teamPlayers: " + team.getTeamPlayers());
		}
		
		return lastPathSegment;
	}

    /**
	 * Insert or Update Team as needed, but just information from detail page
	 * relative to yourWeekDay.
	 * @param uri
	 * @param pl
	 * @return
	 */
	private String insertOrUpdateTeamDetailYourWeekDay(Uri uri, Team team)
	{
		// insertem al team les dades amb day = day
		ContentValues values = new ContentValues();
		values.put(Supermanager.MyTeam.ID_EQU, team.getIdEqu());
		values.put(Supermanager.MyTeam.DAY, team.getYourWeekDay());
		values.put(Supermanager.MyTeam.NAME, team.getName());
		values.put(Supermanager.MyTeam.EARNINGS, team.getEarnings());
		values.put(Supermanager.MyTeam.AVERAGE_SEASON, team.getAverageSeason());
		values.put(Supermanager.MyTeam.AVERAGE_VARIATION, team.getAverageVariation());
		
		Uri teamUri = Supermanager.MyTeam.CONTENT_URI;
		String lastPathSegment = "0";
		
		// si update no retorna 1 reg, llavors insert
		if( service.getContentResolver().update(uri, 
				values, 
				Supermanager.MyTeam.ID_EQU+" = ? AND "+
				Supermanager.MyTeam.DAY+" = ? ", 
				new String[]{team.getIdEqu(), team.getYourWeekDay().toString()}) == 0 )
		{
			teamUri = service.getContentResolver().insert(uri, values);
			lastPathSegment = teamUri.getLastPathSegment();
			Log.d(TAG, "Inserting team detail yourWeekDay data [" + team.getName()
					+ "] with Uri [" + teamUri + "] lastPathSegment ["
					+ lastPathSegment + "] with status: " + team.getStatus()
					+ " and teamPlayers: " + team.getTeamPlayers());
		}
		else
		{
			Cursor cursor = service.getContentResolver().
				query(Supermanager.MyTeam.CONTENT_URI, 
					  Supermanager.MyTeam.PROJECTION, 
					  Supermanager.MyTeam.ID_EQU+" = ? AND "+
					  Supermanager.MyTeam.DAY+" = ? ", 
					  new String[]{team.getIdEqu(), team.getYourWeekDay().toString()}, 
					  Supermanager.MyTeam.DEFAULT_SORT_ORDER);
			
			if( cursor.moveToFirst() )
			{
				lastPathSegment = ""+cursor.getLong(0);
				teamUri = ContentUris.withAppendedId(Supermanager.MyTeam.CONTENT_URI, cursor.getLong(0));
			}
			Log.d(TAG, "Updating team detail yourWeekDay data [" + team.getName()
					+ "] with Uri [" + teamUri + "] lastPathSegment ["
					+ lastPathSegment + "] with status: " + team.getStatus()
					+ " and teamPlayers: " + team.getTeamPlayers());
		}
		
		return lastPathSegment;
	}

	/**
	 * Insert or update MyTeamDetail, players info, as needed.
	 * @param idEqu
	 * @param day
	 * @param player
	 * @return
	 */
	public Uri insertOrUpdateMyTeamPlayer(String idEqu, String day, Player player)
	{
		// setejem el vs_team parsejat per la jornada
		if( player.getTeam() != null )
			player.setVsTeam(this.dayMatches.get(player.getTeam()));
		
		// insertem el team
		ContentValues vplayer = new ContentValues();
		vplayer.put(Supermanager.MyTeamDetail.ID_EQU, idEqu);
		vplayer.put(Supermanager.MyTeamDetail.DAY, day);
		vplayer.put(Supermanager.MyTeamDetail.POSITION, player.getTeamPosition());
		vplayer.put(Supermanager.MyTeamDetail.NUM_POSITION, player.getPosition());
		vplayer.put(Supermanager.MyTeamDetail.BUY, player.isBuy()?1:0);
		vplayer.put(Supermanager.MyTeamDetail.SELL, player.isSell()?1:0);
		vplayer.put(Supermanager.MyTeamDetail.CANCEL, player.isCancel()?1:0);
		vplayer.put(Supermanager.MyTeamDetail.CHANGE, player.isChange()?1:0);
		vplayer.put(Supermanager.MyTeamDetail.CODI_PLAYER, player.getCodi());
		vplayer.put(Supermanager.MyTeamDetail.COST, player.getCost());
		vplayer.put(Supermanager.MyTeamDetail.SIGNING_DAY, player.getBuyDay());
		vplayer.put(Supermanager.MyTeamDetail.PRICE, player.getPrice());
		vplayer.put(Supermanager.MyTeamDetail.WIN, player.isVictory()?1:0);
		vplayer.put(Supermanager.MyTeamDetail.RATING, player.getRating());
		vplayer.put(Supermanager.MyTeamDetail.POINTS, player.getPoints());
		vplayer.put(Supermanager.MyTeamDetail.REBOUNDS, player.getRebounds());
		vplayer.put(Supermanager.MyTeamDetail.THREE, player.getThree());
		vplayer.put(Supermanager.MyTeamDetail.ASSISTS, player.getAssistences());
		vplayer.put(Supermanager.MyTeamDetail.RATING_AVERAGE, player.getAverageRating());
		vplayer.put(Supermanager.MyTeamDetail.POINTS_AVERAGE, player.getAveragePoints());
		vplayer.put(Supermanager.MyTeamDetail.REBOUNDS_AVERAGE, player.getAverageRebounds());
		vplayer.put(Supermanager.MyTeamDetail.THREE_AVERAGE, player.getAverageThree());
		vplayer.put(Supermanager.MyTeamDetail.ASSISTS_AVERAGE, player.getAverageAssistences());
		vplayer.put(Supermanager.MyTeamDetail.STATUS, player.getStatus());
		vplayer.put(Supermanager.MyTeamDetail.NACIONALITY, player.getNacionality());
		vplayer.put(Supermanager.MyTeamDetail.NAME, (player.getName() == null)?"":player.getName());
		vplayer.put(Supermanager.MyTeamDetail.TEAM, (player.getTeam() == null)?"":player.getTeam());
		vplayer.put(Supermanager.MyTeamDetail.VS_TEAM, player.getVsTeam());
		vplayer.put(Supermanager.MyTeamDetail.INFO, player.getInfo());

		
		Uri pUri = Supermanager.MyTeamDetail.CONTENT_URI;
		// si update no retorna 1 reg, llavors insert
		if( service.getContentResolver().update(Supermanager.MyTeamDetail.CONTENT_URI, 
				vplayer, 
				Supermanager.MyTeamDetail.ID_EQU+" = ? AND "+
				Supermanager.MyTeamDetail.DAY+" = ? AND "+
				Supermanager.MyTeamDetail.POSITION+" = ? ", 
				new String[]{ idEqu, day, player.getTeamPosition() }) == 0 )
		{
			pUri = service.getContentResolver().insert(
					Supermanager.MyTeamDetail.CONTENT_URI, vplayer);
			Log.d(TAG, "Inserting player["+ player.getTeamPosition() +"] cod[" + player.getCodi() + "] of team ["
					+ idEqu + "] with Uri [" + pUri + "] "
					+ " buy: "+(player.isBuy()?"1":"0")
					+ " sell: "+(player.isSell()?"1":"0")
					+ " cancel: "+(player.isCancel()?"1":"0")
					+ " change: "+(player.isChange()?"1":"0"));
		}
		else
		{
			Cursor cursor = service.getContentResolver().
			query(Supermanager.MyTeamDetail.CONTENT_URI, 
				  Supermanager.MyTeamDetail.PROJECTION, 
				  Supermanager.MyTeamDetail.ID_EQU+" = ? AND "+
				  Supermanager.MyTeamDetail.DAY+" = ? AND "+
				  Supermanager.MyTeamDetail.POSITION+" = ? ", 
				  new String[]{ idEqu, day, player.getTeamPosition() }, 
				  Supermanager.MyTeamDetail.DEFAULT_SORT_ORDER);
		
			if( cursor.moveToFirst() )
			{
				pUri = ContentUris.withAppendedId(Supermanager.MyTeamDetail.CONTENT_URI, cursor.getLong(0));
		
				Log.d(TAG, "Updating player["+ player.getTeamPosition() +"] cod[" + player.getCodi() + "] of team ["
						+ idEqu + "] with Uri [" + pUri + "]"
						+ " buy: "+(player.isBuy()?"0":"1")
						+ " sell: "+(player.isSell()?"0":"1")
						+ " cancel: "+(player.isCancel()?"0":"1")
						+ " change: "+(player.isChange()?"1":"0"));
			}
		}
		return pUri;
	}
}	
